﻿using KeepAccounts.Common.HttpContextUser;
using KeepAccounts.Common.Mappers;
using KeepAccounts.Models.Base;
using KeepAccounts.Models.PageModel;
using KeepAccounts.Repository.UnitOfWork;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace KeepAccounts.Repository.BaseRepository
{

    // KeepAccountsRepository<TEntity>,
    public class BaseRepository<TEntity> : IBaseRepository<TEntity>
            where TEntity : BaseEntity, new()
    {
        protected readonly ISqlSugarClient _db;
        //private IAspNetUser _aspNetUser;
        private readonly IUnitOfWork _unitOfWork;


        internal ISqlSugarClient Db
        {
            get { return _db; }
        }

        //,IAspNetUser aspNetUser
        public BaseRepository(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
            _db = _unitOfWork.GetDbClient();
            //_aspNetUser = aspNetUser;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="model">添加实体</param>
        /// <returns></returns>

        public async Task<int> Add(TEntity model)
        {
            //model.CreateUserID=
            model.ID = model.ID == Guid.Empty ? Guid.NewGuid() : model.ID;
            var insert = _db.Insertable(model);
            return await insert.ExecuteCommandAsync();
        }
        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="model"></param>   
        /// <returns></returns>
        public async Task<int> Add(List<TEntity> model)
        {
            var insert = _db.Insertable(model);
            return await insert.ExecuteCommandAsync();
        }



        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> Delete(TEntity model)
        {
            return await _db.Updateable(model).SetColumns(t => new TEntity() { IsDeleted = true, UpdateTime = DateTime.Now }).ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 根据id删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteById(object id)
        {
            //, UpdateUserID = _aspNetUser.UserId
            return await _db.Updateable<TEntity>().SetColumns(t => new TEntity() { IsDeleted = true, UpdateTime = DateTime.Now }).Where(t => t.ID.ToString() == id.ToString()).ExecuteCommandHasChangeAsync();
        }
        /// <summary>
        /// 根据where条件删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteWhere(Expression<Func<TEntity,bool>> whereLambda)
        {
            //, UpdateUserID = _aspNetUser.UserId
            return await _db.Updateable<TEntity>().SetColumns(t => new TEntity() { IsDeleted = true, UpdateTime = DateTime.Now }).Where(whereLambda).ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 根据id集合删除多个记录
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<bool> DeleteByIds(object[] ids)
        {
            return await _db.Updateable<TEntity>().SetColumns(t => new TEntity()
            {
                IsDeleted = true,
                UpdateTime = DateTime.Now,
                //UpdateUserID=_aspNetUser.UserId
            }).Where(t => ids.ToList().Contains(t.ID))
            .ExecuteCommandHasChangeAsync();
        }
        /// <summary>
        /// 获取数据列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<TEntity>> Query()
        {
            return await _db.Queryable<TEntity>().Where(t => !t.IsDeleted).ToListAsync();
        }

        /// <summary>
        /// 
        /// 根据条件查询数据列表
        /// </summary>
        /// <param name="strWhere">条件</param>
        /// <returns></returns>
        public async Task<List<TEntity>> Query(string strWhere)
        {
            return await _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(!string.IsNullOrEmpty(strWhere), strWhere).ToListAsync();
        }

        /// <summary>
        /// 获取数据列表
        /// </summary>
        /// <param name="whereExpression">查询条件</param>
        /// <param name="IsDelete">是否要查已删除的</param>
        /// <returns>数据列表</returns>
        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, bool IsDelete = false)
        {
            return await _db.Queryable<TEntity>().WhereIF(!IsDelete, t => !t.IsDeleted).WhereIF(whereExpression != null, whereExpression).ToListAsync();
        }
        /// <summary>
        /// 获得数量
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<int> QueryCount(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(whereExpression != null, whereExpression).CountAsync();
        }
        /// <summary>
        /// 查询数据列表并排序
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, string strOrderByFileds)
        {
            return await _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(whereExpression != null, whereExpression).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).ToListAsync();
        }

        /// <summary>
        /// 查询数据列表 并排序 返回查询字段
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public async Task<List<TResult>> Query<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> selectExpression, string strOrderByFileds)
        {
            return await _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(whereExpression != null, whereExpression).Select(selectExpression).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).ToListAsync();
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true)
        {
            return await _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(whereExpression != null, whereExpression).OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).ToListAsync();
        }

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="strWhere">查询条件</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public async Task<List<TEntity>> Query(string strWhere, string strOrderByFileds)
        {
            return await _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(!string.IsNullOrWhiteSpace(strWhere), strWhere).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).ToListAsync();
        }

        /// <summary>
        /// Top查询
        /// </summary>
        /// <param name="whereExpression">查询条件</param>
        /// <param name="intTop">前几条</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intTop, string strOrderByFileds)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).WhereIF(whereExpression != null, whereExpression).Take(intTop).ToListAsync();
        }

        /// <summary>
        /// Top查询 Select
        /// </summary>
        /// <param name="whereExpression">查询条件</param>
        /// <param name="intTop">前几条</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public Task<List<TResult>> QuerySelect<TResult>(Expression<Func<TEntity, bool>> whereExpression, int intTop, string strOrderByFileds, Expression<Func<TEntity, TResult>> selectExpression) 
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).WhereIF(whereExpression != null, whereExpression).Select(selectExpression).Take(intTop).ToListAsync();
        }

        /// <summary>
        /// Top查询
        /// </summary>
        /// <param name="strWhere">查询条件</param>
        /// <param name="intTop">前几条</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public Task<List<TEntity>> Query(string strWhere, int intTop, string strOrderByFileds)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(!string.IsNullOrWhiteSpace(strWhere), strWhere).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).Take(intTop).ToListAsync();
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="whereExpression">查询条件</param>
        /// <param name="intPageIndex">当前页码</param>
        /// <param name="intPageSize">分页大小</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intPageIndex, int intPageSize, string strOrderByFileds)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(whereExpression != null, whereExpression).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).ToPageListAsync(intPageIndex, intPageSize);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="strWhere">查询条件</param>
        /// <param name="intPageIndex">当前页码</param>
        /// <param name="intPageSize">分页大小</param>
        /// <param name="strOrderByFileds">排序</param>
        /// <returns></returns>
        public Task<List<TEntity>> Query(string strWhere, int intPageIndex, int intPageSize, string strOrderByFileds)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WhereIF(!string.IsNullOrWhiteSpace(strWhere), strWhere).OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds).ToPageListAsync(intPageIndex, intPageSize);
        }

        /// <summary>
        /// 根据id返回实体
        /// </summary>
        /// <param name="objId">id</param>
        /// <returns></returns>
        public Task<TEntity> QueryById(object objId)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).In(objId).SingleAsync();
        }

        public Task<TEntity> GetEntity(Expression<Func<TEntity, bool>> whereExpression, string orderString = null)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).Where(whereExpression).OrderByIF(!string.IsNullOrEmpty(orderString), orderString).SingleAsync();
        }

        /// <summary>
        /// 是否从缓存中查询数
        /// </summary>
        /// <param name="objId">id</param>
        /// <param name="blnUseCache">是否使用缓存</param>
        /// <returns></returns>
        public Task<TEntity> QueryById(object objId, bool blnUseCache = false)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).WithCacheIF(blnUseCache).In(objId).SingleAsync();
        }

        /// <summary>
        /// 根据id查询多条数据
        /// </summary>
        /// <param name="lstIds"></param>
        /// <returns></returns>
        public Task<List<TEntity>> QueryByIds(object[] lstIds)
        {
            return _db.Queryable<TEntity>().Where(t => !t.IsDeleted).In(lstIds).ToListAsync();
        }

        public async Task<List<TResult>> QueryMuch<T, T2, TResult>(
            Expression<Func<T, T2, object[]>> joinExpression,
            Expression<Func<T, T2, TResult>> selectExpression,
            Expression<Func<T, T2, bool>> whereLambda = null, string orderString = null) where T : class, new()
        {
            return await _db.Queryable(joinExpression).WhereIF(whereLambda != null, whereLambda).OrderByIF(!string.IsNullOrEmpty(orderString), orderString).Select(selectExpression).ToListAsync();
        }

        /// <summary> 
        ///查询-多表查询
        /// </summary> 
        /// <typeparam name="T">实体1</typeparam> 
        /// <typeparam name="T2">实体2</typeparam> 
        /// <typeparam name="T3">实体3</typeparam>
        /// <typeparam name="TResult">返回对象</typeparam>
        /// <param name="joinExpression">关联表达式 (join1,join2) => new object[] {JoinType.Left,join1.UserNo==join2.UserNo}</param> 
        /// <param name="selectExpression">返回表达式 (s1, s2) => new { Id =s1.UserNo, Id1 = s2.UserNo}</param>
        /// <param name="whereLambda">查询表达式 (w1, w2) =>w1.UserNo == "")</param> 
        /// <param name="orderString">排序条件</param> 
        /// <returns>值</returns>
        public async Task<List<TResult>> QueryMuch<T, T2, T3, TResult>(
            Expression<Func<T, T2, T3, object[]>> joinExpression,
            Expression<Func<T, T2, T3, TResult>> selectExpression,
            Expression<Func<T, T2, T3, bool>> whereLambda = null, string orderString = null) where T : class, new()
        {
            return await _db.Queryable(joinExpression).WhereIF(whereLambda != null, whereLambda).OrderByIF(!string.IsNullOrEmpty(orderString), orderString).Select(selectExpression).ToListAsync();
        }

        /// <summary>
        /// 分页查询[使用版本，其他分页未测试]
        /// </summary>
        /// <param name="whereExpression">条件表达式</param>
        /// <param name="pageIndex">页码（下标0）</param>
        /// <param name="intPageSize">页大小</param>
        /// <param name="strOrderByFileds">排序字段，如name asc,age desc</param>
        /// <returns></returns>
        public async Task<PageResultModel<TEntity>> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int pageIndex = 1, int intPageSize = 20, string strOrderByFileds = null)
        {

            RefAsync<int> totalCount = 0;
            var list = await _db.Queryable<TEntity>()
             .Where(t => !t.IsDeleted)
             .OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds)
             .WhereIF(whereExpression != null, whereExpression)
             .ToPageListAsync(pageIndex, intPageSize, totalCount);
            return new PageResultModel<TEntity>() { Count = totalCount, PageIndex = pageIndex, PageSize = intPageSize, List = list };
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public async Task<bool> Update(TEntity entity)
        {
            return await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
        }

        public async Task<bool> Update(TEntity entity, string strWhere)
        {
            //return await Task.Run(() => _db.Updateable(entity).Where(strWhere).ExecuteCommand() > 0);
            return await _db.Updateable(entity).Where(strWhere).ExecuteCommandHasChangeAsync();
        }

        public async Task<bool> Update(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> expression)
        {

            return await _db.Updateable<TEntity>().SetColumns(columns).Where(expression).ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="lstColumns"></param>
        /// <param name="lstIgnoreColumns"></param>
        /// <param name="strWhere"></param>
        /// <returns></returns>
        public async Task<bool> Update(
         TEntity entity,
         List<string> lstColumns = null,
         List<string> lstIgnoreColumns = null,
         string strWhere = ""
           )
        {

            IUpdateable<TEntity> up = _db.Updateable(entity);
            if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0)
            {
                up = up.IgnoreColumns(lstIgnoreColumns.ToArray());
            }
            if (lstColumns != null && lstColumns.Count > 0)
            {
                up = up.UpdateColumns(lstColumns.ToArray());
            }
            if (!string.IsNullOrEmpty(strWhere))
            {
                up = up.Where(strWhere);
            }
            return await up.ExecuteCommandHasChangeAsync();
        }
        /// <summary>
        /// 分页查询
        /// </summary>
        /// <returns></returns>
        public async Task<PageResultModel<TModel>> Pages<TModel>(BasePageQuery<TEntity> query)
        {
            RefAsync<int> totalCount = 0;
            var list = await _db.Queryable<TEntity>()
             .Where(t => !t.IsDeleted)
             .WhereIF(query.WhereLambda != null, query.WhereLambda)
             .OrderByIF(!string.IsNullOrEmpty(query.OrderString), query.OrderString)
             .ToPageListAsync(query.PageIndex, query.PageSize, totalCount);
            return new PageResultModel<TModel>() { Count = totalCount, PageIndex = query.PageIndex, PageSize = query.PageSize, List = list.MapToList<TModel>() };
        }

        /// <summary>
        /// 分页查询 Select
        /// </summary>
        /// <returns></returns>
        public async Task<PageResultModel<TModel>> PagesSelect<TModel>(BasePageQuery<TEntity> query, Expression<Func<TEntity, TModel>> selectExpression)
        {
            RefAsync<int> totalCount = 0;
            var list = await _db.Queryable<TEntity>()
             .Where(t => !t.IsDeleted)
             .WhereIF(query.WhereLambda != null, query.WhereLambda)
             .OrderByIF(!string.IsNullOrEmpty(query.OrderString), query.OrderString)
             .Select(selectExpression)
             .ToPageListAsync(query.PageIndex, query.PageSize, totalCount);
            return new PageResultModel<TModel>() { Count = totalCount, PageIndex = query.PageIndex, PageSize = query.PageSize, List = list.MapToList<TModel>() };
        }
        /// <summary>
        /// 多表查询
        /// </summary>
        /// <returns></returns>

        public async Task<PageResultModel<TResult>> PagesMuch<T, T2, T3, T4, TResult>(
            BasePageQuery<TEntity> query,
           Expression<Func<T, T2, T3, T4, object[]>> joinExpression,
           Expression<Func<T, T2, T3, T4, TResult>> selectExpression,
           Expression<Func<T, T2, T3, T4, bool>> whereLambda = null) where T : class, new()
        {
            RefAsync<int> totalCount = 0;
            var list = await _db.Queryable(joinExpression)
                .WhereIF(whereLambda != null, whereLambda)
                .OrderByIF(!string.IsNullOrEmpty(query.OrderString), query.OrderString)
                .Select(selectExpression)
                .ToPageListAsync(query.PageIndex, query.PageSize, totalCount);

            return new PageResultModel<TResult>() { Count = totalCount, PageIndex = query.PageIndex, PageSize = query.PageSize, List = list };
        }

        /// <summary>
        /// 多表查询
        /// </summary>
        /// <returns></returns>

        public async Task<PageResultModel<TResult>> PagesMuch<T, T2, T3, TResult>(
            BasePageQuery<TEntity> query,
           Expression<Func<T, T2, T3, object[]>> joinExpression,
           Expression<Func<T, T2, T3, TResult>> selectExpression,
           Expression<Func<T, T2, T3, bool>> whereLambda = null) where T : class, new()
        {
            RefAsync<int> totalCount = 0;
            var list = await _db.Queryable(joinExpression)
                .WhereIF(whereLambda != null, whereLambda)
                .OrderByIF(!string.IsNullOrEmpty(query.OrderString), query.OrderString)
                .Select(selectExpression)
                .ToPageListAsync(query.PageIndex, query.PageSize, totalCount);

            return new PageResultModel<TResult>() { Count = totalCount, PageIndex = query.PageIndex, PageSize = query.PageSize, List = list };
        }


        public async Task<PageResultModel<TResult>> PagesMuch<T, T2, TResult>(
         BasePageQuery<TEntity> query,
        Expression<Func<T, T2, object[]>> joinExpression,
        Expression<Func<T, T2, TResult>> selectExpression,
        Expression<Func<T, T2, bool>> whereLambda = null) where T : class, new()
        {
            RefAsync<int> totalCount = 0;
            var list = await _db.Queryable(joinExpression)
                .WhereIF(whereLambda != null, whereLambda)
                .OrderByIF(!string.IsNullOrEmpty(query.OrderString), query.OrderString)
                .Select(selectExpression)
                .ToPageListAsync(query.PageIndex, query.PageSize, totalCount);

            return new PageResultModel<TResult>() { Count = totalCount, PageIndex = query.PageIndex, PageSize = query.PageSize, List = list };
        }



        public async Task<PageResultModel<TResult>> PagesMuchGroupBy<T, T2, TResult>(
  BasePageQuery<TEntity> query,
 Expression<Func<T, T2, object[]>> joinExpression,
  Expression<Func<T, T2, object>> groupByExpression,
 Expression<Func<T, T2, TResult>> selectExpression,
 Expression<Func<T, T2, bool>> whereLambda = null) where T : class, new()
        {
            RefAsync<int> totalCount = 0;
            var list = await _db.Queryable(joinExpression)
                .WhereIF(whereLambda != null, whereLambda)
                .OrderByIF(!string.IsNullOrEmpty(query.OrderString), query.OrderString)
                .GroupBy(groupByExpression)
                .Select(selectExpression)
                .ToPageListAsync(query.PageIndex, query.PageSize, totalCount);

            return new PageResultModel<TResult>() { Count = totalCount, PageIndex = query.PageIndex, PageSize = query.PageSize, List = list };
        }


        public Task<DbResult<bool>> UseTranAsync(Action action, Action<Exception> errorCallBack = null)
        {

            return _db.Ado.UseTranAsync(action, errorCallBack);
        }
        /// <summary>
        /// 开启事务
        /// </summary>
        public void BeginTran()
        {
            _db.Ado.BeginTran();
        }
        /// <summary>
        /// 提交事务
        /// </summary>
        public void CommitTran()
        {
            _db.Ado.CommitTran();
        }
        /// <summary>
        /// 回滚事务
        /// </summary>
        public void RollbackTran()
        {
            _db.Ado.RollbackTran();
        }
    }
}
